package vindex

import (
	"fmt"
	"log"

	ds "github.com/tendermint/tendermint/my_app/querylayer/vindex/dstree"
	hnsw "github.com/tendermint/tendermint/my_app/querylayer/vindex/go-hnsw"
	ivf "github.com/tendermint/tendermint/my_app/querylayer/vindex/ivf"
)

// Vindex 接口定义
type Vindex interface {
	BuildIndex(dimension int) error
	InsertData(object_id string, data interface{}) error
	DeleteData(object_id string) error
	KnnQuery(data interface{}, k int, ef int) ([]string, [][]float32, []byte)
}

// ImageVindex 实现 Vindex 接口的图像索引
type ImageVindex struct {
	hnswindex *hnsw.Hnsw_Index
	obnum     int
}

func (iv *ImageVindex) BuildIndex(dimension int) error {
	iv.hnswindex = hnsw.New_Hnsw_Index(dimension)
	iv.obnum = 1
	log.Printf("Building image index for dimension: %v\n", dimension)
	return nil
}

func (iv *ImageVindex) InsertData(object_id string, data interface{}) error {
	interfaceValue := data.([]float32)
	err := iv.hnswindex.Insert(iv.obnum+1, object_id, interfaceValue)
	iv.obnum++
	//fmt.Printf("Inserting image data: %v\n", data)
	return err
}

func (iv *ImageVindex) DeleteData(object_id string) error {
	//fmt.Printf("Deleting image data: %v\n", object_id)
	return iv.hnswindex.Delete(object_id)
}

func (iv *ImageVindex) KnnQuery(data interface{}, k int, ef int) ([]string, [][]float32, []byte) {
	interfaceValue := data.([]float32)
	objIDs, vectors, _ := iv.hnswindex.Knn_Search(interfaceValue, k)
	fmt.Printf("Performing KNN query for image data: k: %d\n", k)
	return objIDs, vectors, nil
}

// SeriesVindex 实现 Vindex 接口的序列索引
type SeriesVindex struct {
	dstree *ds.Dstree_Index
}

func (sv *SeriesVindex) BuildIndex(dimension int) error {
	index_settings := &ds.Dstree_Index_Settings{
		TimeseriesSize: int16(dimension),
		MaxLeafSize:    20, //测试用20
	}
	sv.dstree = ds.DstreeIndexInit(index_settings)
	fmt.Printf("Building series index for dimension: %v\n", dimension)
	return nil
}

func (sv *SeriesVindex) InsertData(object_id string, data interface{}) error {
	interfaceValue := data.([]float32)
	err := sv.dstree.InsertData(object_id, interfaceValue)
	//fmt.Printf("Inserting series data: %v\n", data)
	return err
}

func (sv *SeriesVindex) DeleteData(object_id string) error {
	sv.dstree.DeleteData(object_id)
	fmt.Printf("Deleting image data: %v\n", object_id)
	return sv.dstree.DeleteData(object_id)
}

func (sv *SeriesVindex) KnnQuery(data interface{}, k int, ef int) ([]string, [][]float32, []byte) {
	interfaceValue := data.([]float32)
	objIDs, vectors, _ := sv.dstree.Knn_search(interfaceValue, k)
	fmt.Printf("Performing KNN query for series k: %d\n", k)
	return objIDs, vectors, nil
}

type TextVindex struct {
	index *ivf.InvertedIndex
	obnum int
}

func (tv *TextVindex) BuildIndex(dimension int) error {
	tv.index = ivf.NewInvertedIndex()
	tv.index.CalculateIDFAndSortPostings()
	tv.obnum = 0
	fmt.Printf("Building text index for dimension: %v\n", dimension)
	return nil
}

func (tv *TextVindex) InsertData(object_id string, data interface{}) error {
	interfaceValue := data.([]float32)
	bow := ivf.BOW{
		ID:     tv.obnum,
		Vector: interfaceValue,
	}
	err := tv.index.Insert(object_id, bow)
	tv.index.CalculateIDFAndSortPostings()
	tv.obnum++
	//fmt.Printf("Inserting text data: %v\n", data)
	return err
}

func (tv *TextVindex) DeleteData(object_id string) error {
	return tv.index.Delete(object_id)
}

func (tv *TextVindex) KnnQuery(data interface{}, k int, ef int) ([]string, [][]float32, []byte) {
	interfaceValue := data.([]float32)
	objIDs, vectors, _ := tv.index.Knn_Search(interfaceValue, k)
	fmt.Printf("Performing KNN query for KnnQuery k: %d\n", k)
	return objIDs, vectors, nil
}
